/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef TEST_EVENTS_H_
#define TEST_EVENTS_H_


#include <time.h>

#include "testcase.h"
#include "../src/events.h"

class test_events : public testcase {
public:
	class demo_event_listener:public tri::events::mouse_listener{
	public:
		demo_event_listener():pressed_count(0),click_count(0){}
		virtual ~demo_event_listener(){}
		
		virtual void on_mouse_event(tri::events::event_entity* src,const tri::mouse_event& m){
			
			switch(m.event){
			case tri::CLICKED:
				click_count++;
				break;
			case tri::PRESSED:
				pressed_count++;
				break;
			}
			
		}
		
		int pressed_count;
		int click_count;
	};
	
	
	test_events() :
		testcase() {};
	virtual ~test_events() {};

	inline virtual void run_tests() {
		cout<<"\n*********************************"<<endl;
		cout<<"*"<<endl;
		cout<<"* Running Event Tests"<<endl;
		cout<<"*"<<endl;
		cout<<"*********************************"<<endl;
		testMotionEvents();
		testActionEvents();
		testEventDispatching();
		testEventDispatchingAndActionEvents();
		
	}
	
private:
	inline void testMotionEvents() {
		
		//test defualt state
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusRequestEntity(NULL));
		
		tri::events::event_entity e1,e2;
		
		tri::mouse_event event_moved(0,0,0,0,tri::NONE,tri::MOVED);
		
		
		/**
		 * 
		 *  A : No object
		 *  B : Enter Object1
		 *  C : Exit Object1
		 *  D : Enter Object2
		 *  E : Exit Object2
		 * 
		 */
		
		
		//A
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
		
		//B
		tri::events::_events_process::process_mouse_event(event_moved,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		
		//C
		tri::events::_events_process::process_mouse_event(event_moved,NULL);	
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
		//D
		tri::events::_events_process::process_mouse_event(event_moved,&e2);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e2));
		
		//C
		tri::events::_events_process::process_mouse_event(event_moved,NULL);	
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
		//B
		tri::events::_events_process::process_mouse_event(event_moved,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		
		
		//D
		tri::events::_events_process::process_mouse_event(event_moved,&e2);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e2));
		
		//C
		tri::events::_events_process::process_mouse_event(event_moved,NULL);	
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));

	}
	
	inline void testActionEvents() {
		//test defualt state
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusRequestEntity(NULL));
		
		tri::events::event_entity e1,e2;
		
		
		tri::mouse_event event_pressed_l(0,0,0,0,tri::BUTTON_LEFT,tri::PRESSED);
		tri::mouse_event event_released_l(0,0,0,0,tri::BUTTON_LEFT,tri::RELEASED);
		tri::mouse_event event_moved(0,0,0,0,tri::NONE,tri::MOVED);
		
		
		//A
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
		
		//B
		tri::events::_events_process::process_mouse_event(event_moved,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		
		tri::events::_events_process::process_mouse_event(event_pressed_l,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		
		tri::events::_events_process::process_mouse_event(event_released_l,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		
		
		tri::events::_events_process::process_mouse_event(event_moved,NULL);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
		//A
		tri::events::_events_process::process_mouse_event(event_pressed_l,NULL);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
	}
	
	
	inline void testEventDispatching(){
		//test defualt state
		
		tri::events::event_entity e1,e2;
		demo_event_listener l1,l2;
		
		tri::mouse_event event_released_l(0,0,0,0,tri::BUTTON_LEFT,tri::CLICKED);
		
		e1.addMouseListener(&l1);
		
		assert(l1.click_count==0);
		e1.dispatchMouseEvent(&e1,event_released_l);
		assert(l1.click_count==1);
		
		e1.dispatchMouseEvent(&e1,event_released_l);
		e1.dispatchMouseEvent(&e1,event_released_l);
		e1.dispatchMouseEvent(&e1,event_released_l);
		assert(l1.click_count==4);
		
		e1.addMouseListener(&l2);
		assert(l2.click_count==0);
		
		e1.dispatchMouseEvent(&e1,event_released_l);
		e1.dispatchMouseEvent(&e1,event_released_l);
		e1.dispatchMouseEvent(&e1,event_released_l);
		assert(l1.click_count==7);
		assert(l2.click_count==3);
		
		e1.removeMouseListener(&l1);
		
		e1.dispatchMouseEvent(&e1,event_released_l);
		e1.dispatchMouseEvent(&e1,event_released_l);
		e1.dispatchMouseEvent(&e1,event_released_l);
		assert(l1.click_count==7);
		assert(l2.click_count==6);
		
	}
	
	
	inline void testEventDispatchingAndActionEvents(){
		//test defualt state
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusRequestEntity(NULL));
		
		tri::events::event_entity e1;
		demo_event_listener l1;
		e1.addMouseListener(&l1);
		
		
		tri::mouse_event event_pressed_l(0,0,0,0,tri::BUTTON_LEFT,tri::PRESSED);
		tri::mouse_event event_released_l(0,0,0,0,tri::BUTTON_LEFT,tri::RELEASED);
		tri::mouse_event event_moved(0,0,0,0,tri::NONE,tri::MOVED);
		
		
		//A
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
		
		//B
		tri::events::_events_process::process_mouse_event(event_moved,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		
		
		assert(l1.pressed_count==0);
		tri::events::_events_process::process_mouse_event(event_pressed_l,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		assert(l1.pressed_count==1);
		
		assert(l1.click_count==0);
		tri::events::_events_process::process_mouse_event(event_released_l,&e1);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(&e1));
		assert(l1.click_count==1);
		
		tri::events::_events_process::process_mouse_event(event_moved,NULL);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(&e1));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
		
		//A
		tri::events::_events_process::process_mouse_event(event_pressed_l,NULL);
		assert(tri::events::_events_process::getSingleton()->assertPressedEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertFocusEntity(NULL));
		assert(tri::events::_events_process::getSingleton()->assertMouseOverEntity(NULL));
	}
	

};

#endif /*TEST_EVENTS_H_*/
